﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GoodTrader.GTSystem
{
    // 시스템 상태 : 초기상태, 파이발견상태, 4개저점발견 상태, 진입상태, 본절설정상태, 익절상태, 손절상태, 본절상태
    public enum P4T_STATE { INIT = 0, PIE_FOUND, POINT4_FOUND, ENTERED, NOLOSS_SET, FINISHED_PROFIT, FINISHED_LOSS, FINISHED_NOLOSS};
    /*
     * @brief : 이 시스템은 고점이나 저점이 2개연속으로 만들어졌을 때를 기준으로 진입점을 설정하여 매매한다.
     * 파이는 고점이 연속으로 2개만들어지고 첫번째 봉을 기준으로 5일선을 깨면서 동시에 첫번째 봉의 저가를 4번 갱신하면 파이가 확정된다.
     * 이 점을 파이 확정점이라 한다.
     * 파이 확정점이 만들어 지고 5일선을 깨고 2틱이상 위로 올라오면 매도진입한다.
     * 연속고점이 발견되고 파이 확정점이 찾기까지 다음 파이 조사는 이루어지지 않는다.
     * 고점연속후에 고점을 깨는 봉이 나오면 안된다.
     * 손절은 진입점에서 -4틱이며 손절이 나오면 그 파이는 사라진다.
     * @진입기준 :
     * @손절기준 :
     * @청산기준 :
     */ 
    public class CP4TrackSystem : CTraderSystem
    {
        
        // 이전에 마지막으로 수행한 ConstIndex 
        private int m_LastConstIndex = 0;
        public int LastConstIndex
        {
            get { return m_LastConstIndex; }
            set { m_LastConstIndex = value; }
        }

        // 신호를 발생시키고자 하는 상품코드
        private string m_Code = "";
        public string Code
        {
            get { return m_Code; }
            set { m_Code = value; }
        }

        private P4T_STATE m_HighSysState = P4T_STATE.INIT;
        private P4T_STATE m_LowSysState = P4T_STATE.INIT;
        
        // 진입 기준을 판단할 데이터 셋 객체
        private GTDownload.CpDataSet mCpDataSetObj = null;
        public GTDownload.CpDataSet CpDataSetObj
        {
            get { return mCpDataSetObj; }
            set { mCpDataSetObj = value; }
        }

        private void InitHigh()
        {
            // 모든 값을 초기화 해준다.
            m_P4T_High_LowVal = 0.0; // 파이 생성후의 최초 봉의 저점
            m_P4T_High_LowCount = 0; // 파이 생성후의 저점갱신 개수
            m_P4T_High_LowestVal = 0.0; // 파이 생성후의 최저값
            m_P4T_High_HighVal = 0.0; // 파이 생성초기의 최고값
            m_P4T_High_LossVal = 0.0; // 손절 설정값.
            m_P4T_High_NoLossVal = 0.0; // 본절 설정값.
            m_P4T_High_EntryVal = 0.0; // 진입가.
            m_P4T_High_LiqVal = 0.0; // 청산가격

            m_HighSysState = P4T_STATE.INIT;
        }

        private void InitLow()
        {
            // 모든 값을 초기화 해준다.
            m_P4T_Low_LowVal = 0.0; // 파이 생성후의 최초 봉의 저점
            m_P4T_Low_HighCount = 0; // 파이 생성후의 저점갱신 개수
            m_P4T_Low_HighestVal = 0.0; // 파이 생성후의 최저값
            m_P4T_Low_HighVal = 0.0; // 파이 생성초기의 최고값
            m_P4T_Low_LossVal = 0.0; // 손절 설정값.
            m_P4T_Low_NoLossVal = 0.0; // 본절 설정값.
            m_P4T_Low_EntryVal = 0.0; // 진입가.
            m_P4T_Low_LiqVal = 0.0; // 청산가격

            m_LowSysState = P4T_STATE.INIT;
        }

        /*
         * @brief : 이 함수는 데이터 속에서 고점파이 확정점을 찾는다.
         */ 
        public int FindPieConfirmPoint(ref double a_EntryPoint)
        {
            bool pieStarted = false;
            bool pieEnterCondCompleted = false;
            double lowVal = 0.0;
            double lowCount = 0;
            double lowestVal = 0.0;
            for(int i = 1; i < mCpDataSetObj.FutureTickData.High.Length; i++)
            {
                double firstH = mCpDataSetObj.FutureTickData.High[i - 1];
                double secondH = mCpDataSetObj.FutureTickData.High[i];
                double firstL = mCpDataSetObj.FutureTickData.Low[i - 1];
                double secondL = mCpDataSetObj.FutureTickData.Low[i];
                double ma = mCpDataSetObj.FutureTickData.MA[i];
                // 5일선 이동평균 데이터
                double curMA = mCpDataSetObj.FutureTickData.MA[i];
                // 파이 진입 조건이 완성된 시점에서 
                if (pieEnterCondCompleted == true)
                {
                    // 현재 고점이 5일 이동평균 보다 2틱 이상 위에 있으면 진입 조건이 된다.
                    if (secondH >= ma + 0.1)
                    {
                        a_EntryPoint = ma + 0.1;
                        return i;
                    }
                }
                if (firstH == secondH)
                {
                    pieStarted = true;
                    lowVal = firstL;
                    lowestVal = Math.Min(firstL, secondL);
                }
                if (pieStarted == true)
                {
                    if (secondL < lowVal && secondL < ma)
                    {
                        lowCount++;
                        lowVal = secondL;
                    }
                }
                // 파이나타인 이후로 진입할 때까지 최저점을 갱신해 준다.
                if (secondL < lowestVal)
                    lowestVal = secondL;

                // 파이 진입 조건 확정
                if (lowCount >= 4)
                {
                    pieEnterCondCompleted = true;
                }
            }

            return -1;
        }


        private double m_P4T_High_LowVal = 0.0; // 파이 생성후의 최초 봉의 저점
        private double m_P4T_High_LowCount = 0; // 파이 생성후의 저점갱신 개수
        private double m_P4T_High_LowestVal = 0.0; // 파이 생성후의 최저값
        private double m_P4T_High_HighVal = 0.0; // 파이 생성초기의 최고값
        private double m_P4T_High_LossVal = 0.0; // 손절 설정값.
        private double m_P4T_High_NoLossVal = 0.0; // 본절 설정값.
        private double m_P4T_High_EntryVal = 0.0; // 진입가.
        private double m_P4T_High_LiqVal = 0.0; // 청산가격

        private void FindHighSysState(int a_Index)
        {
            if (a_Index < 1)
                return;
            int curTime = (int)mCpDataSetObj.FutureTickData.Time[a_Index];

            if (curTime > GTGlobal.SysEndTime)
                return;

            int constIndex = (int)mCpDataSetObj.FutureTickData.ConstIndex[a_Index];

            double firstH = mCpDataSetObj.FutureTickData.High[a_Index - 1];
            double secondH = mCpDataSetObj.FutureTickData.High[a_Index];

            double firstL = mCpDataSetObj.FutureTickData.Low[a_Index - 1];
            double secondL = mCpDataSetObj.FutureTickData.Low[a_Index];

            // 5일선 이동평균 데이터
            double curMA = mCpDataSetObj.FutureTickData.MA[a_Index];

            

            if (m_HighSysState == P4T_STATE.INIT ||
                m_HighSysState == P4T_STATE.FINISHED_LOSS ||
                m_HighSysState == P4T_STATE.FINISHED_NOLOSS ||
                m_HighSysState == P4T_STATE.FINISHED_PROFIT)
            {
                if (firstH == secondH)
                {
                    // 상태를 변화시킨다.
                    m_HighSysState = P4T_STATE.PIE_FOUND;
                    m_P4T_High_LowVal = firstL;
                    m_P4T_High_LowestVal = Math.Min(firstL, secondL);
                    m_P4T_High_HighVal = firstH;
                }
            }
            else if (m_HighSysState == P4T_STATE.PIE_FOUND)
            {
                // PIE 고점보다 크면 다시 초기상태로 되돌아 간다.
                if (secondH > m_P4T_High_HighVal)
                {
                    // 초기상태로 되돌아 간다.
                    InitHigh();
                }
                else
                {
                    // 현재 저가보다 작고 5일 이평균 값보다 작으면
                    // m_LowCount의 값을 하나 올린다. 이값이 4가 될때까지 계속한다.
                    if (secondL < m_P4T_High_LowVal && secondL < curMA)
                    {
                        m_P4T_High_LowCount++;
                        m_P4T_High_LowVal = secondL;
                    }

                    // 저가를 4번째 갱신하면 4저점 발견 상태가 된다.
                    if (m_P4T_High_LowCount >= 4)
                    {
                        m_HighSysState = P4T_STATE.POINT4_FOUND;
                    }
                }
            }
            else if (m_HighSysState == P4T_STATE.POINT4_FOUND)
            {
                // PIE 고점보다 크면 다시 초기상태로 되돌아 간다.
                if (secondH > m_P4T_High_HighVal)
                {
                    // 초기상태로 되돌아 간다.
                    InitHigh();
                }
                else
                {
                    // 현재 고점이 5일 이동평균 보다 1틱 초과하면 진입 조건이 된다.
                    if (secondH > curMA + 0.05)
                    {
                        m_HighSysState = P4T_STATE.ENTERED;
                        // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                        Sell(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매도진입", m_Code, curMA + 0.1, 1, "1", "0");
                        // 진입가를 넣어준다.
                        m_P4T_High_EntryVal = curMA + 0.1;
                        // 손절을 설정한다. - 진입점에서 4틱 위에 정한다.
                        m_P4T_High_LossVal = m_P4T_High_EntryVal + 0.2;
                        // 진입까지의 최저점을 확정한다.
                        if (secondL < m_P4T_High_LowestVal)
                            m_P4T_High_LowestVal = secondL;
                    }
                }
            }
            else if (m_HighSysState == P4T_STATE.ENTERED)
            {
                // 고가가 손절 범위를 넘어서면 손절을 한다.
                if (secondH > m_P4T_High_LossVal)
                {
                    // 손절로 인한 청산 신호를 만들어 신호 목록에 넣어준다.
                    // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                    ExitSell(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매도손절", m_Code, m_P4T_High_LossVal, 1, "2", "0");
                    // 시스템 상태는 손절 상태로 바뀐다.
                    m_HighSysState = P4T_STATE.FINISHED_LOSS;
                    InitHigh();
                }
                else
                {
                    // 고가가 진입전 최저점 보다 작으면 본절을 설정한다.
                    if (secondH < m_P4T_High_LowestVal)
                    {
                        m_HighSysState = P4T_STATE.NOLOSS_SET;
                        // 진입가에 한틱 감하여 본절가를 설정한다.
                        m_P4T_High_NoLossVal = m_P4T_High_EntryVal - 0.05;
                        // 진입가에 0.8을 감하여 청산가를 설정한다.
                        m_P4T_High_LiqVal = m_P4T_High_EntryVal - 0.8;
                    }
                }
            }
            else if (m_HighSysState == P4T_STATE.NOLOSS_SET)
            {
                // 고가가 본절 설정가보다 크면 본절로 인한 청산신호를 만들어 내보낸다.
                if (secondH > m_P4T_High_NoLossVal)
                {
                    m_HighSysState = P4T_STATE.FINISHED_NOLOSS;
                    // 여기서 본절 신호를 만들어 목록에 추가해 준다.
                    // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                    ExitSell(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매도본절", m_Code, m_P4T_High_NoLossVal, 1, "2", "0");
                    InitHigh();
                }
                else
                {
                    // 고가가 5일이평선 값보다 크고, 저가가 청산가보다 작으면 청산 신호를 만들어 내보낸다.
                    if (secondH > curMA && secondL < m_P4T_High_LiqVal)
                    {
                        m_HighSysState = P4T_STATE.FINISHED_PROFIT;
                        // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                        ExitSell(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매도익절", m_Code, secondL, 1, "2", "0");
                        InitHigh();
                    }
                }
            }

            // 파이 발견이후 저점을 계속 갱신해 준다.
            if (m_HighSysState == P4T_STATE.PIE_FOUND ||
                m_HighSysState == P4T_STATE.POINT4_FOUND)
            {
                if (secondL < m_P4T_High_LowestVal)
                    m_P4T_High_LowestVal = secondL;
            }

            if (curTime == GTGlobal.SysEndTime && 
                (m_HighSysState == P4T_STATE.ENTERED || m_HighSysState == P4T_STATE.NOLOSS_SET) )
            {
                ExitSell(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이고점시스템종료익절", m_Code, secondL, 1, "2", "0");
                InitHigh();
            }

        }

        private double m_P4T_Low_LowVal = 0.0; // 파이 생성초기의 최저값
        private double m_P4T_Low_HighCount = 0; // 파이 생성후의 고점갱신 개수
        private double m_P4T_Low_HighestVal = 0.0; // 파이 생성후의 최고값
        private double m_P4T_Low_HighVal = 0.0; // 파이 생성 최초봉의 고점값.
        private double m_P4T_Low_LossVal = 0.0; // 손절 설정값.
        private double m_P4T_Low_NoLossVal = 0.0; // 본절 설정값.
        private double m_P4T_Low_EntryVal = 0.0; // 진입가.
        private double m_P4T_Low_LiqVal = 0.0; // 청산가격

        private void FindLowSysState(int a_Index)
        {
            if (a_Index < 1)
                return;

            int curTime = (int)mCpDataSetObj.FutureTickData.Time[a_Index];

            if (curTime > GTGlobal.SysEndTime)
                return;

            int constIndex = (int)mCpDataSetObj.FutureTickData.ConstIndex[a_Index];

            double firstH = mCpDataSetObj.FutureTickData.High[a_Index - 1];
            double secondH = mCpDataSetObj.FutureTickData.High[a_Index];

            double firstL = mCpDataSetObj.FutureTickData.Low[a_Index - 1];
            double secondL = mCpDataSetObj.FutureTickData.Low[a_Index];


            // 5일선 이동평균 데이터
            double curMA = mCpDataSetObj.FutureTickData.MA[a_Index];

            if (m_LowSysState == P4T_STATE.INIT ||
                m_LowSysState == P4T_STATE.FINISHED_LOSS ||
                m_LowSysState == P4T_STATE.FINISHED_NOLOSS ||
                m_LowSysState == P4T_STATE.FINISHED_PROFIT)
            {
                if (firstL == secondL)
                {
                    // 상태를 변화시킨다.
                    m_LowSysState = P4T_STATE.PIE_FOUND;
                    m_P4T_Low_LowVal = firstL;
                    m_P4T_Low_HighestVal = Math.Max(firstH, secondH);
                    m_P4T_Low_HighVal = firstH;
                }
            }
            else if (m_LowSysState == P4T_STATE.PIE_FOUND)
            {
                // 현재 저가가 PIE 저점보다 작으면 다시 초기상태로 되돌아 간다.
                if (secondL < m_P4T_Low_LowVal)
                {
                    // 초기상태로 되돌아 간다.
                    InitLow();
                }
                else
                {
                    // 현재 고가보다 크고 5일 이평균 값보다 크면
                    // m_HighCount의 값을 하나 올린다. 이값이 4가 될때까지 계속한다.
                    if (secondH > m_P4T_Low_HighVal && secondH > curMA)
                    {
                        m_P4T_Low_HighCount++;
                        m_P4T_Low_HighVal = secondH;
                    }

                    // 고가를 4번째 갱신하면 4고점 발견 상태가 된다.
                    if (m_P4T_Low_HighCount >= 4)
                    {
                        m_LowSysState = P4T_STATE.POINT4_FOUND;
                    }
                }
            }
            else if (m_LowSysState == P4T_STATE.POINT4_FOUND)
            {
                // PIE 저점보다 작으면 다시 초기상태로 되돌아 간다.
                if (secondL < m_P4T_Low_LowVal)
                {
                    // 초기상태로 되돌아 간다.
                    InitLow();
                }
                else
                {
                    // 현재 저점이 5일 이동평균 보다 1틱 미만이면 진입 조건이 된다.
                    if (secondL < curMA - 0.05)
                    {
                        m_LowSysState = P4T_STATE.ENTERED;
                        // 진입가를 넣어준다.
                        m_P4T_Low_EntryVal = curMA - 0.1;
                        // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                        Buy(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매수진입", m_Code, m_P4T_Low_EntryVal, 1, "1", "0");
                        // 손절을 설정한다. - 진입점에서 4틱 밑에 정한다.
                        m_P4T_Low_LossVal = m_P4T_Low_EntryVal - 0.2;
                        // 진입까지의 최고점을 확정한다.
                        if (secondH > m_P4T_Low_HighestVal)
                            m_P4T_Low_HighestVal = secondH;
                    }
                }
            }
            else if (m_LowSysState == P4T_STATE.ENTERED)
            {
                // 저가가 손절 범위를 넘어서면 손절을 한다.
                if (secondL < m_P4T_Low_LossVal)
                {
                    // 손절로 인한 청산 신호를 만들어 신호 목록에 넣어준다.
                    // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                    ExitBuy(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매수손절", m_Code, m_P4T_Low_LossVal, 1, "2", "0");
                    // 시스템 상태는 손절 상태로 바뀐다.
                    m_LowSysState = P4T_STATE.FINISHED_LOSS;
                    InitLow();
                }
                else
                {
                    // 저가가 진입전 최고점 보다 크면 본절을 설정한다.
                    if (secondL > m_P4T_Low_HighestVal)
                    {
                        m_LowSysState = P4T_STATE.NOLOSS_SET;
                        // 진입가에 한틱 감하여 본절가를 설정한다.
                        m_P4T_Low_NoLossVal = m_P4T_Low_EntryVal + 0.05;
                        // 진입가에 0.8을 더하여 청산가를 설정한다.
                        m_P4T_Low_LiqVal = m_P4T_Low_EntryVal + 0.8;
                    }
                }
            }
            else if (m_LowSysState == P4T_STATE.NOLOSS_SET)
            {
                // 저가가 본절 설정가보다 작으면 본절로 인한 청산신호를 만들어 내보낸다.
                if (secondL < m_P4T_Low_NoLossVal)
                {
                    m_LowSysState = P4T_STATE.FINISHED_NOLOSS;
                    // 여기서 본절 신호를 만들어 목록에 추가해 준다.
                    // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                    ExitBuy(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매수본절", m_Code, m_P4T_Low_NoLossVal, 1, "2", "0");
                    InitLow();
                }
                else
                {
                    // 저가가 5일이평선 값보다 작고, 고가가 청산가보다 크면 청산 신호를 만들어 내보낸다.
                    if (secondL < curMA && secondH > m_P4T_Low_LiqVal)
                    {
                        m_LowSysState = P4T_STATE.FINISHED_PROFIT;
                        // 여기서 신호발생이 되었으므로 신호를 만들어 신호 목록에 넣어 준다.
                        ExitBuy(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이매수익절", m_Code, secondH, 1, "2", "0");
                        InitLow();
                    }
                }
            }

            // 파이 발견이후 저점을 계속 갱신해 준다.
            if (m_LowSysState == P4T_STATE.PIE_FOUND ||
                m_LowSysState == P4T_STATE.POINT4_FOUND)
            {
                if (secondH > m_P4T_Low_HighestVal)
                    m_P4T_Low_HighestVal = secondH;
            }

            if (curTime == GTGlobal.SysEndTime &&
                (m_LowSysState == P4T_STATE.ENTERED || m_LowSysState == P4T_STATE.NOLOSS_SET))
            {
                ExitBuy(constIndex, constIndex, mCpDataSetObj.FutureTickData.Time[a_Index], "파이저점시스템종료익절", m_Code, secondH, 1, "2", "0");
                InitLow();
            }

            // 마지막으로 수행한 것을 저장해 놓는다.
            m_LastConstIndex = (int)mCpDataSetObj.FutureTickData.ConstIndex[a_Index];
            //Console.WriteLine("last run index" + a_Index.ToString());
            //Console.WriteLine("last run const index" + m_LastConstIndex.ToString());
        }
        /*
         * @brief : 이 함수는 시스템을 수행한다.
         */ 
        public void Run()
        {
            int lastIndex = mCpDataSetObj.FutureTickData.FindIndexByConstIndex(m_LastConstIndex);
            int constindex = (int)mCpDataSetObj.FutureTickData.ConstIndex[GTGlobal.MaxDownloadCount - 1];
            //Console.WriteLine("current run index" + lastIndex.ToString());
            //Console.WriteLine("current run constindex" + constindex.ToString());
            Console.WriteLine("High Sys State" + m_HighSysState.ToString());
            Console.WriteLine("Low Sys State" + m_LowSysState.ToString());
            for (int i = lastIndex; i <= GTGlobal.MaxDownloadCount - 1; i++)
            {
                FindHighSysState(i);
            }
            for (int i = lastIndex; i <= GTGlobal.MaxDownloadCount - 1; i++)
            {
                FindLowSysState(i);
            }
        }

        /*
         * @brief 이 함수는 주어진 범위에 대하여 시스템을 실행한다.
         * @param a_SIndex : 봉의 시작 인덱스
         * @param a_EIndex : 봉의 종료 인덱스
         */ 
        public void Run(int a_SIndex, int a_EIndex)
        {
            //Console.WriteLine("current run index" + lastIndex.ToString());
            //Console.WriteLine("current run constindex" + constindex.ToString());
            InitBuySignalList();
            InitSellSignalList();

            for (int i = a_SIndex; i <= a_EIndex; i++)
            {
                FindHighSysState(i);
            }
            for (int i = a_SIndex; i <= a_EIndex; i++)
            {
                FindLowSysState(i);
            }
        }

        public void PreRun(int a_SIndex, int a_EIndex)
        {
            InitHigh();
            for (int i = a_SIndex; i <= a_EIndex; i++)
            {
                FindHighSysState(i);
            }
            InitLow();
            for (int i = a_SIndex; i <= a_EIndex; i++)
            {
                FindLowSysState(i);
            }
        }

        public int FindPieState(ref double a_EntryPoint)
        {
            // 신호 목록을 모두 지운다. 
            m_SignalManager.ClearSignalList();

            bool pieStarted = false;
            bool pieEnterCondCompleted = false;
            double lowVal = 0.0;
            double lowCount = 0;
            double lowestVal = 0.0;
            for (int i = 1; i < mCpDataSetObj.FutureTickData.High.Length; i++)
            {
                double firstH = mCpDataSetObj.FutureTickData.High[i - 1];
                double secondH = mCpDataSetObj.FutureTickData.High[i];
                double firstL = mCpDataSetObj.FutureTickData.Low[i - 1];
                double secondL = mCpDataSetObj.FutureTickData.Low[i];
                double ma = mCpDataSetObj.FutureTickData.MA[i];
                // 5일선 이동평균 데이터
                double curMA = mCpDataSetObj.FutureTickData.MA[i];
                // 파이 진입 조건이 완성된 시점에서 
                if (pieEnterCondCompleted == true)
                {
                    // 현재 고점이 5일 이동평균 보다 2틱 이상 위에 있으면 진입 조건이 된다.
                    if (secondH >= ma + 0.1)
                    {
                        a_EntryPoint = ma + 0.1;
                        return i;
                    }
                }
                if (firstH == secondH)
                {
                    pieStarted = true;
                    lowVal = firstL;
                    lowestVal = Math.Min(firstL, secondL);
                }
                if (pieStarted == true)
                {
                    if (secondL < lowVal && secondL < ma)
                    {
                        lowCount++;
                        lowVal = secondL;
                    }
                }
                // 파이나타인 이후로 진입할 때까지 최저점을 갱신해 준다.
                if (secondL < lowestVal)
                    lowestVal = secondL;

                // 파이 진입 조건 확정
                if (lowCount >= 4)
                {
                    pieEnterCondCompleted = true;
                }
            }

            return -1;
        }
    }
}
